#pragma once

// 专门设计进行命令解析和执行的模块，做好模块化与解耦工作

#include <iostream>
#include <string>
#include <vector>
#include <cstdio>

class Command
{
private:
    bool IsSafe(const std::string &cmd)
    {
        for (auto &e : _string_list)
            if (e == cmd)
                return true;
        return false;
    }

public:
    Command()
    {
        _string_list.emplace_back("ls -l");
        _string_list.emplace_back("pwd");
        _string_list.emplace_back("whoami");
        _string_list.emplace_back("clear");
        _string_list.emplace_back("cal");
    }

    std::string Exec(const std::string &cmd)
    {
        std::string res;
        if (!IsSafe(cmd))
        {
            std::cout << "cmd is not safe" << std::endl;
            res += "cmd is not safe";
        }
        else
        {
            // 命令是安全的
            FILE *fp = popen(cmd.c_str(), "r"); // popen:pipe + fork + exec
            if (fp == nullptr)
            {
                std::cout << "popen error" << std::endl;
                res += "please try again";
            }
            else
            {
                // 命令的执行内容在fd相应的缓冲区中
                char buffer[1024] = {0};

                // 由于文件缓冲区中的结果可能是多行的，因此fgets需要while读取,因为fgets默认是读取到换行符为止
                while (fgets(buffer, sizeof(buffer), fp) != nullptr)
                    res += buffer;
                pclose(fp);
            }
        }
        return res;
    }

private:
    std::vector<std::string> _string_list; // 控制命令的合法性
};